<template>
  <div>
    <el-card shadow="hover" class="mt-20">
      <el-form
        label-width="120px"
        ref="spuFormRef"
        :model="spuListFormData"
        :rules="spuListFormRules"
      >
        <el-form-item label="SPU名称" prop="spuName">
          <el-input
            placeholder="Please输入SPU名称"
            v-model="spuListFormData.spuName"
          />
        </el-form-item>
        <el-form-item label="品牌" prop="tmId">
          <el-select v-model="spuListFormData.tmId" placeholder="请选择">
            <el-option
              v-for="tm in trademarkList"
              :key="tm.id"
              :label="tm.tmName"
              :value="tm.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="SPU描述" prop="description">
          <el-input
            v-model="spuListFormData.description"
            :rows="3"
            type="textarea"
            placeholder="SPU描述"
          />
        </el-form-item>
        <el-form-item label="SPU图片" prop="spuImageList">
          <!-- 上传图片 -->
          <el-upload
            accept="image/*"
            v-model:file-list="spuListFormData.spuImageList"
            :action="BASE_URL + '/admin/product/upload'"
            list-type="picture-card"
            :on-preview="handlePictureCardPreview"
            :before-upload="beforeAvatarUpload"
            :limit="3"
            :on-exceed="handleUploadExceed"
            :on-success="handleUploadSuccess"
          >
            <el-icon><Plus /></el-icon>
            <template #tip>
              <div class="el-upload__tip">
                只能上传jpg/png文件，且不超过200kb
              </div>
            </template>
          </el-upload>
          <el-dialog v-model="dialogVisible" width="30%">
            <el-image :src="dialogImageUrl" class="spu-img" />
          </el-dialog>
        </el-form-item>
        <el-form-item label="销售属性" prop="spuSaleAttrList">
          <el-select
            :placeholder="`还有${filterBaseSaleAttrList.length}个未选择`"
            v-model="selectedSaleAttr"
            class="mr-10"
          >
            <el-option
              v-for="baseSaleAttr in filterBaseSaleAttrList"
              :key="baseSaleAttr.id"
              :label="baseSaleAttr.name"
              :value="`${baseSaleAttr.id}:${baseSaleAttr.name}`"
            ></el-option>
          </el-select>
          <el-button
            type="primary"
            :icon="Plus"
            :disabled="!selectedSaleAttr"
            @click="addSaleAttr"
            >添加销售属性
          </el-button>
          <el-table
            :data="spuListFormData.spuSaleAttrList"
            border
            class="mt-20"
          >
            <el-table-column
              label="序号"
              type="index"
              align="center"
              width="80px"
            />
            <el-table-column prop="saleAttrName" label="属性名" width="200px" />
            <el-table-column label="属性名称列表">
              <template v-slot="{ row }">
                <el-tag
                  v-for="(tag, index) in row.spuSaleAttrValueList"
                  :key="tag.baseSaleAttrId"
                  class="mr-10"
                  closable
                  :type="tag.type"
                  @close="delSpuSaleAttrValue(row, index)"
                >
                  {{ tag.saleAttrValueName }}
                </el-tag>
                <el-input
                  size="small"
                  v-if="row.isShowEdit"
                  ref="inputRef"
                  class="spu-input"
                  v-model="saleAttrValueName"
                  @blur="switchShow(row)"
                />
                <el-button
                  v-else
                  :icon="Plus"
                  size="small"
                  @click="edit(row)"
                />
              </template>
            </el-table-column>
            <el-table-column label="操作">
              <template v-slot="{ $index }">
                <el-button
                  type="danger"
                  :icon="Delete"
                  size="small"
                  @click="deleSaleAttr($index)"
                ></el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="addOrUpdateSpu">保存</el-button>
          <el-button @click="cancel">取消</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script lang="ts">
export default {
  name: "AddSpuList",
};
</script>

<script lang="ts" setup>
import type {
  BaseSaleAttrList,
  AllSpuSaleAttrItem,
  AllSpuSaleAttrList,
  AllSpuItem,
  AllSpuImageItem,
} from "@/api/product/model/spuModel";
import {
  getBaseSaleAttrListApi,
  addSpuApi,
  getSpuImageListApi,
  getSpuSaleAttrListApi,
  updateSpuInfoUrl,
} from "@/api/product/spu";
import { ref, defineEmits, reactive, onMounted, computed, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { Plus, Delete } from "@element-plus/icons-vue";
import type { UploadProps, UploadUserFile } from "element-plus";
import type { TrademarkList } from "@/api/product/model/trademarkModel";
import { getAllTrademarkListApi } from "@/api/product/trademark";
import { beforeAvatarUpload } from "@/utils/tools";
import { useCategoryStore } from "@/stores/category";
import { useSpuStore } from "@/stores/spu";

// 基础销售属性列表
const baseSaleAttrList = ref<BaseSaleAttrList>([]);
// 品牌属性列表
const trademarkList = ref<TrademarkList>([]);

onMounted(async () => {
  baseSaleAttrList.value = await getBaseSaleAttrListApi();
});
onMounted(async () => {
  trademarkList.value = await getAllTrademarkListApi();
});
onMounted(async () => {
  const id = spuStore.spuItem.id;
  if (!id) return;
  //服务器存储的图片数据：imgName/imgUrl
  // upload组件需要图片数据: name/url

  const spuImageList = await getSpuImageListApi(id);

  spuListFormData.spuImageList = spuImageList.map((item) => {
    const img = item as AllSpuImageItem;
    return {
      name: img.imgName,
      url: img.imgUrl,
      response: {
        data: img.imgUrl,
      },
    };
  });
});
onMounted(async () => {
  const id = spuStore.spuItem.id;
  if (!id) return;
  spuListFormData.spuSaleAttrList = await getSpuSaleAttrListApi(id);
});
/*************************表单校验*************************** */
const spuFormRef = ref();
const spuStore = useSpuStore();

// 表单数据
const spuListFormData = reactive<AllSpuItem<UploadUserFile>>({
  tmId: spuStore.spuItem.tmId,
  spuName: spuStore.spuItem.spuName,
  description: spuStore.spuItem.description,
  spuImageList: [],
  spuSaleAttrList: [],
});

//自定义校验函数
const spuSaleAttrListValidator = (
  rule: any,
  value: AllSpuSaleAttrList,
  callback: any
) => {
  /**
   * rule 规则信息对象
   * value 校验数据的值
   * callback 是一个函数，必须要调用
   *    callback(); 校验通过
   *    callback(new Error('错误信息')); 校验失败
   */

  //  至少添加一个销售属性
  if (!value.length) {
    callback(new Error("请至少添加一个销售属性"));
    return;
  }
  // 每个销售属性至少添加一个属性值
  if (value.some((spuSaleAttr) => !spuSaleAttr.spuSaleAttrValueList.length)) {
    callback(new Error("每个销售属性至少添加一个属性值"));
    return;
  }
  //一定要调用，校验通过
  callback();
};

// 表单校验规则
const spuListFormRules = reactive({
  spuName: [{ required: true, message: "请输入SPU名称", trigger: "blur" }],
  tmId: [{ required: true, message: "请选择品牌名称", trigger: "change" }],
  description: [{ required: true, message: "请输入SPU描述", trigger: "blur" }],
  spuImageList: [{ required: true, message: "请上传SPU图片" }],
  spuSaleAttrList: [
    {
      required: true,
      // message: "请添加SPU销售属性",
      validator: spuSaleAttrListValidator,
    },
  ],
});

/***********************上传图片************************* */

const BASE_URL = import.meta.env.VITE_API_URL;

const dialogImageUrl = ref("");
const dialogVisible = ref(false);

const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!;
  dialogVisible.value = true;
};

const handleUploadExceed = () => {
  ElMessage.error("只能上传10张图片");
};

//图片上传成功的回调
const handleUploadSuccess = () => {
  spuFormRef.value.clearValidate(["spuImageList"]);
};

// 保存
const categoryStore = useCategoryStore();
const addOrUpdateSpu = async () => {
  try {
    await spuFormRef.value.validate();

    const id = spuStore.spuItem.id;

    const { spuName, tmId, description, spuImageList, spuSaleAttrList } =
      spuListFormData;

    const data = {
      category3Id: categoryStore.category3Id,
      spuName,
      tmId,
      description,
      //通过Upload组件收集到图片数据: name\url\response
      // 发送请求给服务器图片数据： imgName/imgUrl
      spuImageList: spuImageList.map((item) => {
        const img = item as UploadUserFile;
        return {
          imgName: img.name,
          imgUrl: (img.response as { data: string }).data,
        };
      }),
      spuSaleAttrList,
    };

    if (id) {
      await updateSpuInfoUrl({
        ...data,
        id,
      });
    } else {
      await addSpuApi(data);
    }

    ElMessage({
      type: "success",
      message: `${id ? "更新" : "添加"}SPU成功`,
    });
    cancel();
  } catch (e) {
    console.log(e);
  }
};

/************************添加销售属性*************************** */
// 销售属性功能按键
const selectedSaleAttr = ref("");

// 添加销售属性
const addSaleAttr = () => {
  const [id, name] = selectedSaleAttr.value.split(":");

  spuListFormData.spuSaleAttrList.push({
    baseSaleAttrId: +id,
    saleAttrName: name,
    spuSaleAttrValueList: [],
    isShowEdit: false,
  });

  //清空选中的数据
  selectedSaleAttr.value = "";
};

// 计算销售属性的变化
const filterBaseSaleAttrList = computed(() => {
  // 对基础销售属性列表baseSaleAttrList进行过滤
  return baseSaleAttrList.value.filter((baseSaleAttr) => {
    // 判断单个销售属性在不在表格中（spuFormData.spuSaleAttrList）
    // 找到了返回值true，希望过滤，返回false
    return !spuListFormData.spuSaleAttrList.some(
      (spuSaleAttr) => spuSaleAttr.baseSaleAttrId === baseSaleAttr.id
    );
  });
});

//删除属性
const deleSaleAttr = (index: number) => {
  spuListFormData.spuSaleAttrList.splice(index, 1);
};

/*****************************编辑模式&&显示模式********************************** */
const inputRef = ref();
//点击"+"号
const edit = async (row: AllSpuSaleAttrItem) => {
  row.isShowEdit = true;

  await nextTick();
  inputRef.value.focus();
};

//输入的销售名称
const saleAttrValueName = ref();

// 切换显示模式,当input失去光标时触发
const switchShow = (row: AllSpuSaleAttrItem) => {
  row.isShowEdit = false;

  row.spuSaleAttrValueList.push({
    baseSaleAttrId: row.baseSaleAttrId,
    // saleAttrName: "string",
    saleAttrValueName: saleAttrValueName.value, //销售值名称
    // spuId: 0,
  });

  // 失去光标时，清空输入框中的内容
  saleAttrValueName.value = "";
};

const delSpuSaleAttrValue = (row: AllSpuSaleAttrItem, index: number) => {
  row.spuSaleAttrValueList.splice(index, 1);
};

const emit = defineEmits(["setIsShow"]);
const cancel = () => {
  emit("setIsShow", 1);
};
</script>

<style scoped>
.spu-img {
  width: 100%;
}

.spu-input {
  width: 150px;
}
</style>
